import os

import yaml

from utils.logging_tool.recordlog import logs

""" 处理yaml 测试用例文件 """


def get_yaml_files(directory):
    """
    获取指定目录下以及子目录下的所有文件
    :param directory: 指定目录
    :return:
    """
    # 将所有的yaml文件路径添加到列表中
    yaml_files_path = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith('.yaml') or file.endswith('.yml'):
                file_path = os.path.join(root, file).replace("\\", '/')
                yaml_files_path.append(file_path)

    return yaml_files_path


def get_testcase_yaml(file):
    """
    获取yaml测试文件，并进行处理
    :param file: 指定文件
    :return:
    """
    # 处理用例等级转成严重等级 blocker、critical、normal、minor、trivial
    rank_mapping = {'P1': 'blocker',
                    'P2': 'critical',
                    'P3': 'normal',
                    'P4': 'minor',
                    'P5': 'trivial'}
    key_list = list(rank_mapping.keys())
    testcase_list = []
    try:
        with open(file, 'r', encoding='utf-8') as f:
            data = yaml.safe_load(f)
            # 判断 baseInfo 数量 大于1的为多接口，小于等于1的为单接口
            if len(data) <= 1:  # 键值对小于 1 为单接口，只有一个baseInfo，单接口需要将testCase部分与baseInfo整合一起作为一个用例
                yam_data = data[0]
                base_info = yam_data.get('baseInfo')

                # 模块名称
                feature = base_info.get('feature', None)
                if feature is None:
                    base_info['feature'] = '未定义模块名称'

                # 接口名称
                story = base_info.get('api_name', None)
                if story is None:
                    base_info['api_name'] = '未定义接口名称'

                for testcase in yam_data.get('testCase'):
                    # 用例名称
                    case_name = testcase.get('case_name', None)
                    if case_name is None:
                        testcase['case_name'] = '未定义用例名称'

                    # 用例等级
                    rank = testcase.get('rank', 'P3')  # rank 字段不存在 默认 P3 对应严重程度一般
                    if rank in key_list:
                        testcase['rank'] = rank_mapping.get(rank)
                    else:
                        testcase['rank'] = 'normal'  # 不填或者除了P1-P5都默认为P3

                    param = [base_info, testcase]
                    testcase_list.append(param)

                return testcase_list
            else:
                # 列表数据  包含多个baseInfo，一个baseInfo 对应一个 testCase
                for yam_data in data:
                    base_info = yam_data.get('baseInfo')

                    # 模块名称
                    feature = base_info.get('feature', None)
                    if feature is None:
                        base_info['feature'] = '未定义模块名称'

                    # 接口名称
                    story = base_info.get('api_name', None)
                    if story is None:
                        base_info['api_name'] = '未定义接口名称'

                    testcase = yam_data.get('testCase')
                    for ts in testcase:
                        # 用例名称
                        case_name = ts.get('case_name', None)
                        if case_name is None:
                            ts['case_name'] = '未定义用例名称'

                        # 用例等级
                        rank = ts.get('rank', 'P3')
                        if rank in key_list:
                            ts['rank'] = rank_mapping.get(rank)
                        else:
                            ts['rank'] = 'normal'

                    testcase_list.append(yam_data)
                return testcase_list

    except UnicodeDecodeError:
        logs.error(f"【{file}】文件编码格式错误，--尝试使用utf-8编码解码YAML文件时发生了错误，请确保你的yaml文件是UTF-8格式！")
    except FileNotFoundError:
        logs.error(f'【{file}】文件未找到，请检查路径是否正确')
    except Exception as e:
        logs.error(f'获取【{file}】文件数据时出现未知错误: {str(e)}')


def get_testcase_yaml_all(directory):
    """
    对指定目录下所有的yaml文件内处理后的测试用例进行合并（列表合并）
    :param directory: 指定目录
    :return:
    """
    testcases = []
    files = get_yaml_files(directory)
    for file in files:
        testcase = get_testcase_yaml(file)
        testcases.extend(testcase)
    return testcases
